package com.sjgtw.cloud.auth.controller;

import com.sjgtw.cloud.auth.service.SysLoginService;
import com.sjgtw.cloud.auth.vo.LoginBody;
import com.sjgtw.cloud.client.entity.UserInfo;
import com.sjgtw.cloud.client.http.HttpVerb;
import com.sjgtw.cloud.client.oauth.OAuthClient;
import com.sjgtw.cloud.client.oauth.OauthClientConfig;
import com.sjgtw.cloud.client.oauth.builder.ServiceBuilder;
import com.sjgtw.cloud.client.oauth.builder.api.FouraOAuthApi;
import com.sjgtw.cloud.client.oauth.model.Token;
import com.sjgtw.cloud.client.oauth.model.Verifier;
import com.sjgtw.cloud.client.oauth.oauth.OAuthService;
import com.sjgtw.cloud.common.core.domain.R;
import com.sjgtw.cloud.common.core.utils.IdUtils;
import com.sjgtw.cloud.common.core.utils.ServletUtils;
import com.sjgtw.cloud.common.core.utils.StringUtils;
import com.sjgtw.cloud.common.security.service.TokenService;
import com.sjgtw.cloud.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>Title: 登录、登出、Token</p>
 * <p>Description: </p>
 * @author Admin
 * @date 2021-4-9
 */
@RestController
public class TokenController
{
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysLoginService sysLoginService;
 
    @Autowired
    OauthClientConfig oauthClientConfig;

    /**
     * <p>Title: 系统登录</p>
     * <p>Description: </p>
     * @param form
     * @return
     */
    @PostMapping("/login")
    public R<?> login(@RequestBody LoginBody form)
    {
        LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
        return R.ok(tokenService.createToken(userInfo));
    }
    
    /**
     * <p>Title: 系统登出</p>
     * <p>Description: </p>
     * @param form
     * @return
     */
    @DeleteMapping("/logout")
    public R<?> logout(HttpServletRequest request)
    {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser))
        {
            String username = loginUser.getUsername();
            tokenService.delLoginUser(loginUser.getToken());
            sysLoginService.logout(username);
        }
        return R.ok();
    }
    
    /**
     * <p>Title: 刷新令牌有效期</p>
     * <p>Description: </p>
     * @param form
     * @return
     */
    @PostMapping("/refresh")
    public R<?> refresh(HttpServletRequest request)
    {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser))
        {
            tokenService.refreshToken(loginUser);
            return R.ok();
        }
        return R.ok();
    }

    /**
     * <p>Title: Oauth2.0-SSO登录</p>
     * <p>Description: 获取认证地址</p>
     * @param form
     * @return
     */
    @GetMapping("/login/authorize")
    public R<?> loginAuthorize()
    {
        String state = IdUtils.fastUUID();
        OAuthService service =
                new ServiceBuilder()
                        .provider(FouraOAuthApi.class)
                        .apiKey(oauthClientConfig.getClientId())
                        .apiSecret(oauthClientConfig.getClientSecret())
                        .callback(oauthClientConfig.getRedirectUri())
                        .state(state)
                        .build();

        String redirect_uri = service.getAuthorizationUrl(null);
        Map<String, Object> redirectMap = new HashMap<>();
        redirectMap.put("redirect_uri", redirect_uri);
        logger.debug("*****SSO****redirect_uri: {}",redirect_uri);
        return R.ok(redirectMap);
    }

    /**
     * <p>Title: Oauth2.0-SSO回调</p>
     * <p>Description: </p>
     * @param form
     * @return
     */
    @GetMapping("/login/callback")
    public R<?> loginCallback(@RequestParam("code") String code,
                              @RequestParam("state") String state, HttpServletResponse response) {
        Token accessToken = null;
        try {
            OAuthService service = new ServiceBuilder().provider(FouraOAuthApi.class)
                    .apiKey(oauthClientConfig.getClientId())
                    .apiSecret(oauthClientConfig.getClientSecret())
                    .callback(oauthClientConfig.getRedirectUri()).state(state).build();

            Verifier verifier = new Verifier(code);
            Token EMPTY_TOKEN = null;
            accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
            logger.debug("*****SSO****accessToken-message: {}",  accessToken.getAccess_token());
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail(302, oauthClientConfig.getErrorEndpoint() + "?errcode=LoginErr-007&msg="
                    + ServletUtils.urlEncode("认证服务无法访问"));
        }
        UserInfo callbackUser = new UserInfo();
        try {
            OAuthClient restClient = new OAuthClient(oauthClientConfig.getBaseUrl()+"/api/oauth/v20/me", HttpVerb.POST);
            restClient.addBearerAuthorization(accessToken.getAccess_token());
            callbackUser = restClient.getUserInfo(accessToken.getAccess_token(), code);
            logger.debug("*****SSO****callbackUser {}", callbackUser);
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail(302, oauthClientConfig.getErrorEndpoint() + "?errcode=LoginErr-004&msg="
                    + ServletUtils.urlEncode("无法获取登录用户"));
        }
        LoginUser userInfo = sysLoginService.callback(callbackUser);
        return R.ok(tokenService.createToken(userInfo));

    }


}
